package com.xnyzc.lhy.didi.service.impl.xiecheng;

import com.alibaba.fastjson.JSON;
import com.xnyzc.lhy.common.component.amap.GouldMapUtils;
import com.xnyzc.lhy.common.component.redis.RedisCommon;
import com.xnyzc.lhy.common.constant.MqConstant;
import com.xnyzc.lhy.common.constant.RedisPrefixConstant;
import com.xnyzc.lhy.common.entity.GouldResult;
import com.xnyzc.lhy.common.entity.Qw;
import com.xnyzc.lhy.common.global.Configuration;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.cms.EVehicleType;
import com.xnyzc.lhy.common.penum.order.EOrderChannelType;
import com.xnyzc.lhy.common.penum.order.EOrderStatus;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.common.util.DateUtil;
import com.xnyzc.lhy.common.util.IDUtil;
import com.xnyzc.lhy.didi.common.constants.EXieChengCallVehType;
import com.xnyzc.lhy.didi.common.constants.EXieChengResponseConstant;
import com.xnyzc.lhy.didi.common.constants.EXieChengVehicleType;
import com.xnyzc.lhy.didi.entity.order.OaCOrderPersonal;
import com.xnyzc.lhy.didi.entity.param.xiecheng.request.*;
import com.xnyzc.lhy.didi.entity.param.xiecheng.response.*;
import com.xnyzc.lhy.didi.mapper.order.OaCOrderPersonalMapper;
import com.xnyzc.lhy.didi.mapper.sys.OaSysOfficeMapper;
import com.xnyzc.lhy.didi.mapper.xiecheng.CityInfoMapper;
import com.xnyzc.lhy.didi.mapper.xiecheng.VehicleInfoMapper;
import com.xnyzc.lhy.didi.mq.MQProducer;
import com.xnyzc.lhy.didi.service.xiecheng.PriceService;
import com.xnyzc.lhy.didi.service.xiecheng.RequsetService;
import com.xnyzc.lhy.order.entity.gps.OaDVehicleGps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service
public class RequestServiceImpl implements RequsetService {

    @Autowired
    private RedisCommon redisCommon;

    @Autowired
    private PriceService priceService;

    @Autowired
    private OaCOrderPersonalMapper oaCOrderPersonalMapper;

    @Autowired
    private CityInfoMapper cityInfoMapper;

    @Autowired
    private VehicleInfoMapper vehicleInfoMapper;

    @Autowired
    private OaSysOfficeMapper oaSysOfficeMapper;

    @Autowired
    private MQProducer producer;

    private Integer channel = EOrderChannelType.xiecheng.getType();

    @Override
    public XieChengResponse queryProduct(QueryProductRequest request) {
        GouldResult.RouteBean router = GouldMapUtils.getStrategy(request.getDuseLocation().getLongitude() + "," + request.getDuseLocation().getLatitude(), request.getAuseLocation().getLongitude() + "," + request.getAuseLocation().getLatitude());
        if (router == null) {
            return XieChengResponse.error();
        }
        List<Long> vehicleTypes = request.getVehicleTypeList();
        if (vehicleTypes == null) {
            vehicleTypes = new ArrayList<>(4);
            vehicleTypes.add(EXieChengVehicleType.vehTypeEconomic.getCode());
            vehicleTypes.add(EXieChengVehicleType.vehTypeComfortable.getCode());
            vehicleTypes.add(EXieChengVehicleType.vehTypeLuxury.getCode());
        }
        Date startDate = DateUtil.convertStringToDate(request.getUseTime());
        int callType = EXieChengCallVehType.getByCode(request.getCategoryCode()).getType();
        String cityCode = getCityIdByCode(request.getFixedLocation().getCityId());
        if (cityCode == null) {
            return XieChengResponse.error();
        }

        HashMap<String, String> mprices = new HashMap<>(8);
        List<ShoppingQueryProductDTO> prices = new ArrayList<>();
        for (Long vehicleType : vehicleTypes) {
            EVehicleType mvehicleType = EXieChengVehicleType.getByType(vehicleType.intValue());
            if (mvehicleType == null) {
                continue;
            }
            HashMap<String, Object> priceMap = priceService.getPriceDetail(channel, cityCode, mvehicleType, callType, startDate, router);
            String estimateId = priceMap.get("estimateId").toString();
            redisCommon.setHashMap(priceMap.get("estimateId").toString(), priceMap, Long.valueOf(86400));
            mprices.put(String.valueOf(vehicleType), estimateId);

            BigDecimal totalFee = getFee(priceMap, "totalFee");

            ShoppingQueryProductDTO shopping = new ShoppingQueryProductDTO();
            shopping.setVehicleType(vehicleType);
            shopping.setPrice(totalFee);
            prices.add(shopping);
        }
        //保存价格关键字集合
        String estimateId = String.valueOf(IDUtil.nextId());
        redisCommon.setHashMap(RedisPrefixConstant.DIDI_ESTIMATE + estimateId, mprices, Long.valueOf(86400));

        QueryProductResponse response = new QueryProductResponse();
        response.wrap(EXieChengResponseConstant.OK);
        response.setPriceMark(estimateId);
        response.setCurrency("CNY");
        response.setQueryResultList(prices);

        return response;
    }

    @Override
    @Deprecated
    /**
     * 原有接口，已弃用
     */
    public XieChengResponse createOrder(CreateOrderRequest request) {
        CreateOrderResponse response = new CreateOrderResponse();
        //查询是否已经接单，已接单不接了
        Long orderId = request.getCtripPurchaseOrderId();
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderId));
        if (personal != null) {
            response.wrap(EXieChengResponseConstant.OK);
            response.setVendorOrderId(String.valueOf(personal.getPersonalId()));
            return response;
        }
        String priceMark = request.getPriceMark();
        HashMap<String, String> tprices = redisCommon.getHashMap(RedisPrefixConstant.DIDI_ESTIMATE + priceMark);
        String estimateId = tprices.get(String.valueOf(request.getVehicleType()));
        if (CheckUtil.strIsEmpty(estimateId)) {
            response.wrap(EXieChengResponseConstant.ERROR_NO_PRICEMARK);
            return response;
        }
        String cityId = getCityIdByCode(request.getFixedLocation().getCityId());
        Long officeId = 1l;//oaSysOfficeMapper.getCompanyByAdCode(cityId);
        if (officeId == null || officeId < 1) {
            response.setMessage(EErrorCode.argCheckErr.getDesc());
            return response;
        }

        HashMap<String, Object> priceMap = redisCommon.getHashMap(estimateId);
        if (priceMap == null) {
            response.wrap(EXieChengResponseConstant.ERROR_EXPIRE_PRICEMARK);
            return response;
        }
        Integer robable = (Integer) priceMap.get("robable");
        Long rulesId = (Long) priceMap.get("rulesId");
        BigDecimal distanceKm = getFee(priceMap, "distanceKm");
        BigDecimal timeCount = getFee(priceMap, "timeCount");
        BigDecimal totalFee = getFee(priceMap, "totalFee");
        BigDecimal drawFee = getFee(priceMap, "drawFee");
        BigDecimal startFee = getFee(priceMap, "startFee");
        BigDecimal emptyFee = getFee(priceMap, "emptyFee");
        BigDecimal specialTimeFee = getFee(priceMap, "specialTimeFee");
        BigDecimal specialDistanceFee = getFee(priceMap, "specialDistanceFee");
        Long personalId = IDUtil.nextId();
        String phone = request.getPassenger().getLocalPhone();
        String realPhone = request.getPassenger().getMaskRealPhone();
        int plength = realPhone.length();
        String phoneSuffix = realPhone.substring(plength - 4, plength);
        String passengerName = request.getPassenger().getName();

        personal = new OaCOrderPersonal();
        personal.setPassengerName(passengerName);
        personal.setDurationTime(timeCount);
        personal.setMilageDistance(distanceKm);
        personal.setTotalFee(totalFee);
        personal.setDrawFee(drawFee);
        personal.setStartFee(startFee);
        personal.setMileageFee(specialTimeFee);
        personal.setEmptyDrivingFee(emptyFee);
        personal.setDistanceFee(specialDistanceFee);
        personal.setPersonalId(personalId);
        personal.setIsCarpool(0);
        personal.setRulesId(rulesId);
        personal.setOrderType(EXieChengCallVehType.getByCode(request.getCategoryCode()).getType());
        personal.setOrderStatus(EOrderStatus.waitingResponse.getType());
        personal.setPassengerPhone(request.getPassenger().getLocalPhone());
        personal.setPassengerPhoneSuffix(phoneSuffix);
        personal.setOrderChannel(EOrderChannelType.xiecheng.getType());
        //personal.setOrderType(ECallVehType.reservation.getType());
        personal.setAppointment(DateUtil.convertStringToDate(request.getUseTime()));
        personal.setCityId(cityId);
        //数据类型不一样，做映射处理
        personal.setVehicleType(EXieChengVehicleType.getByType(request.getVehicleType().intValue()).getValue());
        personal.setOrderNo(orderId.toString());
        personal.setCreateTime(new Date());
        personal.setCreateUser(passengerName);
        personal.setUpdateTime(new Date());
        personal.setUpdateUser(passengerName);
        //位置信息
        personal.setStartLat(request.getDuseLocation().getLatitude().toString());
        personal.setStartLng(request.getDuseLocation().getLongitude().toString());
        personal.setEndLng(request.getAuseLocation().getLongitude().toString());
        personal.setEndLat(request.getAuseLocation().getLatitude().toString());
        personal.setStartAddress(request.getDuseLocation().getDetailAddress());
        personal.setEndAddress(request.getAuseLocation().getDetailAddress());
        personal.setFlightDate(request.getFlightInfo().getTakeOffTime());
        personal.setFlightDelayTime(request.getFlightInfo().getDepartDelayTime());
        personal.setFlightNo(request.getFlightInfo().getFlightNumber());
        //预估价一口价标识
        personal.setChargeType("0");
        personal.setEstimateId(Long.valueOf(priceMark));
        //添加订单到所在地公司下
        personal.setOfficeId(officeId);
        int insert = oaCOrderPersonalMapper.insert(personal);
        if (insert > 0) {
            producer.sendMsg(personal, MqConstant.BIND_DEFAULT_DRIVER, null, 1);
            if (robable == 1) {
                //发送新订单通知
                producer.sendMsg(personal, MqConstant.NOTICE_NEW_ORDER, null, 1);
                //抢单时间为行程开始前两个小时
                long endTime = personal.getAppointment().getTime() - Configuration.DELAY_ROB_BOOKING;
                String bookingKey = RedisPrefixConstant.ORDER_BOOKING + personal.getOfficeId() + ":" + orderId;
                redisCommon.set(bookingKey, JSON.toJSONString(personal));
                redisCommon.addToZSet(RedisPrefixConstant.ORDER_TC_HALL+personal.getCityId(), bookingKey, endTime);
            }

            response.wrap(EXieChengResponseConstant.OK);
            response.setVendorOrderId(String.valueOf(personalId));
            return response;
        } else {
            response.wrap(EXieChengResponseConstant.ERROR);
            return response;
        }
    }

    @Override
    public XieChengResponse updatePassenger(UpdatePassengerRequest request) {
        UpdatePassengerResponse response = new UpdatePassengerResponse();
        Long orderId = request.getCtripPurchaseOrderId();
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderId));
        if (personal == null) {
            response.wrap(EXieChengResponseConstant.ERROR);
            return response;
        }

        String phone = request.getPassenger().getLocalPhone();
        String realPhone = request.getPassenger().getMaskRealPhone();
        int plength = realPhone.length();
        String phoneSuffix = realPhone.substring(plength - 4, plength);
        String passengerName = request.getPassenger().getName();

        personal.setPassengerName(passengerName);
        personal.setPassengerPhone(phone);
        personal.setPassengerPhoneSuffix(phoneSuffix);
        personal.setUpdateUser(passengerName);
        personal.setUpdateTime(new Date());
        int res = oaCOrderPersonalMapper.updateById(personal);

        EXieChengResponseConstant constant = EXieChengResponseConstant.ERROR;
        if (res > 0) {
            constant = EXieChengResponseConstant.OK;
        }
        response.wrap(constant);
        return response;
    }

    @Override
    public XieChengResponse queryDriverLocation(QueryDriverLocationRequest request) {
        QueryDriverLocationResponse response = new QueryDriverLocationResponse();
        List<OrderInfoDTO> orders = request.getOrderInfo();

        List<OrderDriverLocationDTO> locations = new ArrayList<>();
        for (OrderInfoDTO order : orders) {
            Long orderId = order.getCtripPurchaseOrderId();
            OrderDriverLocationDTO location = new OrderDriverLocationDTO();
            location.setCtripPurchaseOrderId(orderId);
            location.wrap(EXieChengResponseConstant.ERROR_NO_ORDERID);

            OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderId));
            if (personal != null) {
                location.wrap(EXieChengResponseConstant.ERROR_NO_DRIVER_LOCATION);
                Long driverId = personal.getDriverId();

                String redisKey = RedisPrefixConstant.GPS_VEH_KEY_PREFIX + driverId;
                String string = redisCommon.getStr(redisKey);
                if (string != null) {
                    OaDVehicleGps oaDVehicleGps = JSON.parseObject(string, OaDVehicleGps.class);
                    if (oaDVehicleGps != null) {

                        DriverLocationDTO mlocation = new DriverLocationDTO();
                        mlocation.setLatitude(new BigDecimal(oaDVehicleGps.getLat()));
                        mlocation.setLongitude(new BigDecimal(oaDVehicleGps.getLng()));
                        mlocation.setCoordinate("GCJ02");
                        mlocation.setSpeed(new BigDecimal(oaDVehicleGps.getSpeed()));
                        mlocation.setLocationTime(DateUtil.convertDateToString(oaDVehicleGps.getUpdateTime()));
                        //FIXME 车头朝向怎么处理？
                        mlocation.setDirection(new BigDecimal(0));
                        location.addDriverLocationDTO(mlocation);
                        location.wrap(EXieChengResponseConstant.OK);
                    }
                }
            }
            locations.add(location);
        }
        response.wrap(EXieChengResponseConstant.OK);
        response.setOrderDriverLocationInfo(locations);
        return response;
    }

    @Override
    public XieChengResponse cancelOrder(CancelOrderRequest request) {
        CancelOrderResponse response = new CancelOrderResponse();
        response.wrap(EXieChengResponseConstant.ERROR);

        Long orderId = request.getCtripPurchaseOrderId();
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderId));
        if (personal == null) {
            response.setMessage(EErrorCode.argCheckErr.getDesc());
            return response;
        }
        if (personal.getOrderStatus() == EOrderStatus.cancelOrderNoNeedPayment.getType()) {
            response.wrap(EXieChengResponseConstant.OK);
        } else {
            personal.setOrderStatus(EOrderStatus.cancelOrderNoNeedPayment.getType());
            personal.setCancelReason(request.getCancelReason());
            personal.setUpdateTime(new Date());

            if (oaCOrderPersonalMapper.updateById(personal) > 0) {
                //删除延时任务所需数据
                String bookingKey = RedisPrefixConstant.ORDER_BOOKING + personal.getOfficeId() + ":" + personal.getOrderNo();
                redisCommon.remove(bookingKey);

                redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_HALL+personal.getCityId(), bookingKey);
                redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_ZSET2, bookingKey);
                redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_ZSET3, bookingKey);
                redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_ZSET4, bookingKey);
                redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_ZSET5, bookingKey);

                //删除rediskey
                String key = RedisPrefixConstant.ORDER_OA_D_ORDER + personal.getOrderNo();
                if (redisCommon.hashKey(key)) {
                    if (CheckUtil.objIsNotEmpty(personal.getDriverId())) {
                        redisCommon.remove(RedisPrefixConstant.ORDER_VEH + personal.getDriverId());
                    }
                    if (CheckUtil.objIsNotEmpty(personal.getUserId())) {
                        redisCommon.remove(RedisPrefixConstant.ORDER_USER + personal.getUserId());
                    }
                    redisCommon.remove(key);
                }
                response.wrap(EXieChengResponseConstant.OK);
            }
        }
        return response;
    }

    @Override
    public XieChengResponse pushVehicleInfo(PushVehicleInfoRequest request) {
        PushVehicleInfoResponse response = new PushVehicleInfoResponse();
        response.wrap(EXieChengResponseConstant.ERROR);

        int res = 0;
        List<VehicleInfoDTO> vehicleInfos = request.getData();
        for (VehicleInfoDTO vehicleInfo : vehicleInfos) {
            //检查有无该信息
            int size = vehicleInfoMapper.getCountById(vehicleInfo.getVehicleId());
            if(size <= 0){
                res=vehicleInfoMapper.insert(vehicleInfo);
            }else {
                res = vehicleInfoMapper.updateById(vehicleInfo);
            }
            if (res < 1) {
                return response;
            }
        }
        response.wrap(EXieChengResponseConstant.OK);
        return response;
    }

    @Override
    public XieChengResponse pushCityInfo(PushCityInfoRequest request) {
        PushCityInfoResponse response = new PushCityInfoResponse();
        response.wrap(EXieChengResponseConstant.ERROR);

        int res = 0;
        List<CityInfoDTO> cityInfos = request.getData();
        for (CityInfoDTO cityInfo : cityInfos) {
            //检查有无信息
            int size = cityInfoMapper.getCountById(cityInfo.getCityId());
            if(size <= 0){
                res = cityInfoMapper.insert(cityInfo);
            }else {
                res = cityInfoMapper.updateById(cityInfo);
            }
            if (res < 1) {
                return response;
            }
        }
        response.wrap(EXieChengResponseConstant.OK);
        return response;
    }

    private String getCityIdByCode(String code) {
        switch (code) {
            case "1": {
                //北京
                return "110100";
            }
            case "2": {
                //上海
                return "310100";
            }
            case "12": {
                //南京
                return "320100";
            }
            case "28": {
                //成都
                return "510100";
            }
            case "42": {
                //海口
                return "460100";
            }
            case "91": {
                //九寨沟
                return "513200";
            }
            case "158":{
                //长春
                return "220100";
            }
            case "39":{
                //乌鲁木齐
                return "650100";
            }
            case "529" : {
                //伊宁
                return "654002";
            }
            case "150" : {
                //牡丹江
                return "231000";
            }
        }
        return null;
    }

    private BigDecimal getFee(HashMap<String, Object> map, String key) {
        Object object = map.get(key);
        if (object == null) {
            return new BigDecimal(0);
        }
        if (object instanceof BigDecimal) {
            return (BigDecimal) object;
        } else {
            return new BigDecimal(object.toString());
        }
    }
}
